#!/usr/bin/env node
/**
 * FigmaMCPWorkflow 自动化编排引擎
 *
 * 职责:
 * - 按phase-manifest.json定义的顺序执行Phase0-5
 * - 自动调用产物生成脚本(phase2:reference等)
 * - 执行质量门控验证(validate:gate)
 * - 管理checkpoint状态与断点恢复
 *
 * 设计约束(遵循CONTRIBUTING.md):
 * - 不修改Phase README内部逻辑（保持Phase自治性）
 * - 不改变phase-manifest.json的phases执行顺序
 * - 遵循Preview-first契约
 * - 质量门控阈值不可降低
 *
 * 用法:
 *   npm run workflow:auto ComponentName
 *   npm run workflow:auto ComponentName --resume Phase3
 *   npm run workflow:auto ComponentName --stop-at Phase2
 */

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const ROOT = process.cwd();
const MANIFEST_PATH = path.join(ROOT, 'Workflow/FigmaMCPWorkflow/phase-manifest.json');

// ==================== 核心执行逻辑 ====================

/**
 * 主编排函数
 */
async function runWorkflow(componentName, options = {}) {
  console.log(`\n${'='.repeat(60)}`);
  console.log(`🚀 FigmaMCPWorkflow 自动化执行`);
  console.log(`   组件: ${componentName}`);
  console.log(`   模式: ${options.resume ? '断点恢复' : '完整执行'}`);
  console.log(`${'='.repeat(60)}\n`);

  // 1. 加载phase-manifest.json
  const manifest = loadManifest();

  // 2. 确定执行范围
  const phases = getPhaseSequence(manifest, options);

  // 3. 创建执行上下文
  const context = {
    componentName,
    rootDir: path.join(ROOT, componentName),
    manifest,
    startTime: new Date().toISOString()
  };

  // 4. 顺序执行各Phase
  let lastCompletedPhase = null;
  for (const phaseName of phases) {
    try {
      console.log(`\n${'▶'.repeat(30)}`);
      console.log(`执行 ${phaseName}`);
      console.log(`${'▶'.repeat(30)}\n`);

      await executePhase(phaseName, context);
      lastCompletedPhase = phaseName;

      if (options.stopAt && phaseName === options.stopAt) {
        console.log(`\n⏸️  已暂停在 ${phaseName}（按用户要求）`);
        break;
      }
    } catch (error) {
      console.error(`\n❌ ${phaseName} 执行失败: ${error.message}`);

      // 保存失败checkpoint
      await saveFailureCheckpoint(componentName, phaseName, error);

      // 尝试错误恢复
      const recovery = await handleError(error, componentName, phaseName);
      if (recovery.action === 'abort') {
        console.log(`\n🛑 工作流已中止`);
        process.exit(1);
      } else if (recovery.action === 'rollback') {
        console.log(`\n↩️  回滚到 ${recovery.rollbackTo}`);
        return runWorkflow(componentName, { resume: recovery.rollbackTo });
      }
    }
  }

  // 5. 生成最终报告
  await generateFinalReport(context, lastCompletedPhase);

  console.log(`\n${'='.repeat(60)}`);
  console.log(`✅ 工作流执行完成`);
  console.log(`   最终Phase: ${lastCompletedPhase}`);
  console.log(`   产物目录: ${context.rootDir}`);
  console.log(`${'='.repeat(60)}\n`);
}

/**
 * 执行单个Phase
 */
async function executePhase(phaseName, context) {
  const phaseConfig = context.manifest.phases[phaseName];
  const componentName = context.componentName;

  // Step 1: 检查前置依赖
  console.log(`📋 检查前置依赖...`);
  await validatePhaseDependencies(phaseName, context);

  // Step 2: 自动生成中间产物
  console.log(`📦 生成中间产物...`);
  await generateIntermediateArtifacts(phaseName, componentName, phaseConfig);

  // Step 3: 执行Phase主流程（提示AI执行README中的步骤）
  console.log(`🤖 执行Phase主流程...`);
  console.log(`   请参考: Workflow/FigmaMCPWorkflow/${phaseName}/README.md`);
  console.log(`   按Runtime Card中的steps依次执行`);

  // 注: 此处为编排层，不替代AI执行Phase内部逻辑
  // AI仍需阅读Phase README并执行具体步骤
  // 编排层只负责前后的自动化任务

  // Step 4: 质量门控验证
  console.log(`\n🚦 执行质量门控验证...`);
  const gateResult = await runPhaseGateValidation(componentName, phaseName);

  if (!gateResult.passed) {
    throw new Error(`质量门控未通过: ${gateResult.failures.map(f => f.name).join(', ')}`);
  }

  console.log(`✅ ${phaseName} 验证通过 (${gateResult.passedCount}/${gateResult.totalChecks})`);

  // Step 5: 更新checkpoint
  await updateCheckpoint(componentName, phaseName, {
    status: 'completed',
    timestamp: new Date().toISOString(),
    qualityMetrics: gateResult.metrics || {},
    artifacts: phaseConfig.outputs.intermediate.filter(a => a.required).map(a => a.path)
  });
}

// ==================== 产物生成逻辑 ====================

/**
 * 自动生成Phase中间产物
 */
async function generateIntermediateArtifacts(phase, componentName, phaseConfig) {
  // 产物路径 → npm脚本映射
  const ARTIFACT_SCRIPT_MAP = {
    'phase1/logs/mcp-calls.json': null, // MCP日志需要运行时拦截，此处跳过
    'phase2/reference-component-comparison.json': 'phase2:reference',
    'phase2/field-mapping.json': 'phase2:field-mapping',
    'phase3/three-layer-validation.json': 'phase3:three-layer'
  };

  const artifacts = phaseConfig.outputs.intermediate || [];

  for (const artifact of artifacts) {
    if (!artifact.required) continue;

    const scriptName = ARTIFACT_SCRIPT_MAP[artifact.path];
    if (!scriptName) continue;

    const artifactPath = path.join(ROOT, componentName, artifact.path);

    // 检查产物是否已存在
    if (fs.existsSync(artifactPath)) {
      console.log(`  ✓ ${artifact.path} (已存在)`);
      continue;
    }

    console.log(`  🔧 生成 ${artifact.path}...`);
    try {
      execSync(`npm run ${scriptName} ${componentName}`, {
        cwd: ROOT,
        stdio: 'inherit'
      });
      console.log(`  ✓ ${artifact.path} (已生成)`);
    } catch (error) {
      console.warn(`  ⚠️  ${artifact.path} 生成失败: ${error.message}`);
      // 非关键产物失败不阻断流程
    }
  }
}

// ==================== 质量门控逻辑 ====================

/**
 * 执行Phase门控验证
 */
async function runPhaseGateValidation(componentName, phaseName) {
  try {
    execSync(`node scripts/phase-gate-validator.js ${componentName} ${phaseName}`, {
      cwd: ROOT,
      stdio: 'inherit'
    });

    // 读取验证结果
    const checkpointPath = getCheckpointPath(componentName, phaseName);
    if (fs.existsSync(checkpointPath)) {
      const checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
      return {
        passed: true,
        passedCount: checkpoint.qualityMetrics ? Object.keys(checkpoint.qualityMetrics).length : 0,
        totalChecks: checkpoint.qualityMetrics ? Object.keys(checkpoint.qualityMetrics).length : 0,
        metrics: checkpoint.qualityMetrics
      };
    }

    return { passed: true, passedCount: 0, totalChecks: 0 };
  } catch (error) {
    return {
      passed: false,
      passedCount: 0,
      totalChecks: 1,
      failures: [{ name: '门控验证失败', error: error.message }]
    };
  }
}

// ==================== Checkpoint管理 ====================

/**
 * 更新checkpoint文件
 */
async function updateCheckpoint(componentName, phaseName, data) {
  const checkpointPath = getCheckpointPath(componentName, phaseName);
  const checkpointDir = path.dirname(checkpointPath);

  if (!fs.existsSync(checkpointDir)) {
    fs.mkdirSync(checkpointDir, { recursive: true });
  }

  // 读取现有checkpoint（如存在）
  let existing = {};
  if (fs.existsSync(checkpointPath)) {
    existing = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
  }

  // 合并数据
  const checkpoint = {
    ...existing,
    phase: phaseName,
    ...data,
    updatedAt: new Date().toISOString()
  };

  fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));
  console.log(`  ✓ Checkpoint已更新: ${checkpointPath}`);
}

/**
 * 保存失败checkpoint
 */
async function saveFailureCheckpoint(componentName, phaseName, error) {
  const checkpointPath = getCheckpointPath(componentName, phaseName);
  const checkpoint = {
    phase: phaseName,
    status: 'failed',
    error: {
      message: error.message,
      stack: error.stack
    },
    timestamp: new Date().toISOString(),
    nextAction: {
      type: 'manual',
      suggestion: `检查 ${phaseName}/README.md 中的验证标准，修复问题后执行: npm run workflow:auto ${componentName} --resume ${phaseName}`
    }
  };

  fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));
  console.log(`\n💾 失败checkpoint已保存: ${checkpointPath}`);
}

function getCheckpointPath(componentName, phaseName) {
  const CHECKPOINT_MAP = {
    'Phase0': 'P0_initialization.json',
    'Phase1': 'P1_figma_data.json',
    'Phase2': 'P2_preview_build.json',
    'Phase3': 'P3_field_design.json',
    'Phase4': 'P4_panel_generation.json',
    'Phase5': 'P5_integration.json'
  };

  const filename = CHECKPOINT_MAP[phaseName];
  return path.join(ROOT, componentName, 'checkpoints', filename);
}

// ==================== 错误处理逻辑 ====================

/**
 * 错误恢复策略
 */
async function handleError(error, componentName, phaseName) {
  const ERROR_RECOVERY_MAP = {
    'ERR_P2_001': { rollbackTo: 'Phase2', autoFix: false },
    'ERR_P3_007': { rollbackTo: 'Phase3', autoFix: true },
    'ERR_P5_TYPE_MISMATCH': { rollbackTo: 'Phase3', autoFix: false }
  };

  // 尝试从错误消息中提取错误码
  const errorCode = extractErrorCode(error.message);
  const recovery = ERROR_RECOVERY_MAP[errorCode];

  if (recovery) {
    if (recovery.autoFix) {
      console.log(`\n🔧 尝试自动修复 ${errorCode}...`);
      // 未来实现: 调用auto-fix脚本
      return { action: 'retry' };
    } else {
      return { action: 'rollback', rollbackTo: recovery.rollbackTo };
    }
  }

  // 默认策略: 中止并等待人工介入
  return { action: 'abort' };
}

function extractErrorCode(message) {
  const match = message.match(/ERR_P\d+_\w+/);
  return match ? match[0] : null;
}

// ==================== 辅助函数 ====================

function loadManifest() {
  if (!fs.existsSync(MANIFEST_PATH)) {
    throw new Error(`phase-manifest.json 不存在: ${MANIFEST_PATH}`);
  }
  return JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8'));
}

function getPhaseSequence(manifest, options) {
  const allPhases = ['Phase0', 'Phase1', 'Phase2', 'Phase3', 'Phase4', 'Phase5'];

  if (options.resume) {
    const resumeIndex = allPhases.indexOf(options.resume);
    if (resumeIndex === -1) {
      throw new Error(`无效的恢复点: ${options.resume}`);
    }
    return allPhases.slice(resumeIndex);
  }

  return allPhases;
}

async function validatePhaseDependencies(phaseName, context) {
  // 简化实现: 检查前置Phase的checkpoint是否存在
  const PHASE_ORDER = ['Phase0', 'Phase1', 'Phase2', 'Phase3', 'Phase4', 'Phase5'];
  const currentIndex = PHASE_ORDER.indexOf(phaseName);

  for (let i = 0; i < currentIndex; i++) {
    const prevPhase = PHASE_ORDER[i];
    const checkpointPath = getCheckpointPath(context.componentName, prevPhase);

    // Phase4是条件执行，可能不存在checkpoint
    if (prevPhase === 'Phase4') continue;

    if (!fs.existsSync(checkpointPath)) {
      throw new Error(`前置Phase未完成: ${prevPhase} checkpoint不存在`);
    }

    const checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
    if (checkpoint.status !== 'completed') {
      throw new Error(`前置Phase未完成: ${prevPhase} status=${checkpoint.status}`);
    }
  }

  console.log(`  ✓ 前置依赖检查通过`);
}

async function generateFinalReport(context, lastPhase) {
  const reportPath = path.join(context.rootDir, 'workflow-execution-report.json');

  const report = {
    component: context.componentName,
    startTime: context.startTime,
    endTime: new Date().toISOString(),
    lastCompletedPhase: lastPhase,
    phases: {}
  };

  // 收集各Phase的质量指标
  const phases = ['Phase0', 'Phase1', 'Phase2', 'Phase3', 'Phase4', 'Phase5'];
  for (const phase of phases) {
    const checkpointPath = getCheckpointPath(context.componentName, phase);
    if (fs.existsSync(checkpointPath)) {
      const checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
      report.phases[phase] = {
        status: checkpoint.status,
        qualityMetrics: checkpoint.qualityMetrics || {}
      };
    }
  }

  fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
  console.log(`\n📊 执行报告已生成: ${reportPath}`);
}

// ==================== CLI入口 ====================

function main() {
  const args = process.argv.slice(2);
  const componentName = args[0];

  if (!componentName) {
    console.error('❌ 缺少组件名称');
    console.error('用法: npm run workflow:auto ComponentName');
    console.error('      npm run workflow:auto ComponentName --resume Phase3');
    console.error('      npm run workflow:auto ComponentName --stop-at Phase2');
    process.exit(1);
  }

  const options = {};
  if (args.includes('--resume')) {
    const resumeIndex = args.indexOf('--resume');
    options.resume = args[resumeIndex + 1];
  }
  if (args.includes('--stop-at')) {
    const stopIndex = args.indexOf('--stop-at');
    options.stopAt = args[stopIndex + 1];
  }

  runWorkflow(componentName, options).catch(error => {
    console.error(`\n❌ 工作流执行失败: ${error.message}`);
    console.error(error.stack);
    process.exit(1);
  });
}

main();
